package com.telit.android.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.google.common.collect.Maps;
import com.telit.android.dao.AppSignInDao;
import com.telit.android.dto.AppSignInDto;
import com.telit.android.entity.AppSignIn;
import com.telit.android.service.AppSignInService;
import com.telit.common.core.utils.FeignUtils;
import com.telit.common.core.utils.Result;
import com.telit.common.entity.DataReturn;
import com.telit.common.enums.ResultCode;
import com.telit.common.exception.ForestBaseException;
import com.telit.common.util.JwtTokenUtils;
import com.telit.firecommand.feign.RemoteFirecommandService;
import com.telit.firecommand.vo.ForesterVO;
import com.telit.upms.feign.RemoteUpmsService;
import com.telit.upms.vo.MicroSysUserVo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;


/**
 * @Author:zhangwei
 * @Description:
 * @Time:Created on 2021/9/1 14:08
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class AppSignInServiceImpl extends ServiceImpl<AppSignInDao, AppSignIn> implements AppSignInService {

    @Autowired
    private RemoteFirecommandService fireCommandFeignClient;

    @Autowired
    private RemoteUpmsService remoteUpmsService;

    /**
     * 新增用户签到信息
     *
     * @param appSignIn
     */
    @Override
    public void add(AppSignIn appSignIn) {
        //如果签到时间为null，获取当前时间作为签到时间
        if (ObjectUtil.isEmpty(appSignIn.getSignInTime())) {
            appSignIn.setSignInTime(new Date());
        }
        //当经纬度不为nul的时候，查询签到地的行政区划
        Double longitude = appSignIn.getLongitude();
        Double latitude = appSignIn.getLatitude();
        DataReturn districtNameAndCodeByPoint = null;
        if (ObjectUtil.isNotEmpty(longitude) && ObjectUtil.isNotEmpty(latitude)) {
            districtNameAndCodeByPoint = fireCommandFeignClient.getDistrictNameAndCodeByPoint(String.valueOf(longitude),
                    String.valueOf(latitude));
        }
        //把经纬度信息设置到签到实体中
        if (districtNameAndCodeByPoint != null && "00000".equals(districtNameAndCodeByPoint.getCode())
                && districtNameAndCodeByPoint.getData() != null) {
            Map<String, String> stringStringMap = Convert.toMap(String.class, String.class,
                    districtNameAndCodeByPoint.getData());
            appSignIn.setDistrictCode(stringStringMap.get("cun"));
            appSignIn.setDistrictName(
                    stringStringMap.get("shengName") + stringStringMap.get("shiName") + stringStringMap.get("xianName")
                            + stringStringMap.get("xiangName") + stringStringMap.get("cunName"));
        } else {
            //设置行政区划名称为“不在行政区划范围内”
            appSignIn.setDistrictName("不在行政区划范围内");
        }

        if (baseMapper.insert(appSignIn) <= 0) {
            throw new ForestBaseException("新增用户签到信息失败");
        }
    }

    /**
     * 分页条件查询用户签到信息
     *
     * @param current
     * @param size
     * @param appSignIn
     *
     * @return
     */
    @Override
    public IPage<AppSignIn> selectByPage(Integer current, Integer size, AppSignIn appSignIn) {
        IPage<AppSignIn> appSignInIPage = new Page<>(current, size);
        QueryWrapper<AppSignIn> wrapper = new QueryWrapper<>();
        wrapper.orderByDesc("sign_in_time");
        return baseMapper.selectPage(appSignInIPage, wrapper);
    }

    /**
     * 无分页条件查询用户签到信息
     *
     * @param appSignIn
     *
     * @return
     */
    @Override
    public List<AppSignIn> selectByNoPage(AppSignIn appSignIn) {
        QueryWrapper<AppSignIn> wrapper = new QueryWrapper<>();
        wrapper.orderByDesc("sign_in_time");
        return baseMapper.selectList(wrapper);
    }

    /**
     * 修改用户签到信息，目前这个功能不会使用到，如果后期需要修改，这个方法需要根据传入的经纬度
     * 查库进行对比，如果不一致，需要把行政区划数据替换掉
     *
     * @param appSignIn
     */
    @Override
    public void updateData(AppSignIn appSignIn) {
        if (baseMapper.updateById(appSignIn) <= 0) {
            throw new ForestBaseException("修改用户签到信息失败");
        }
    }

    /**
     * 根据ID删除用户签到信息
     *
     * @param id
     */
    @Override
    public void deleteById(Long id) {
        if (baseMapper.deleteById(id) <= 0) {
            throw new ForestBaseException("删除用户签到信息失败");
        }
    }

    /**
     * 根据用户ID查询当月签到天数
     *
     * @param userId
     *
     * @return
     */
    @Override
    public int getSignDayNumMonth(Long userId) {
        return baseMapper.selectSignDayNumMonth(userId);
    }

    /**
     * 根据用户ID查询当月签到日信息列表
     *
     * @param userId
     *
     * @return
     */
    @Override
    public List<Map<String, Object>> listSignDayByMonth(Long userId, String signDate) {
        return baseMapper.selectSignDayListMonth(userId, signDate);
    }

    /**
     * 根据用户ID查询当年每个月签到天数
     *
     * @param userId
     * @param year
     *
     * @return
     */
    @Override
    public List<Map<String, Object>> listSignDayNumByYear(Long userId, String year) {
        return baseMapper.selectSignDayNumYear(userId, year);
    }

    /**
     * 根据用户ID和日期（年-月-日）查询日签到信息
     *
     * @param userId
     * @param signDate
     *
     * @return
     */
    @Override
    public AppSignIn getSignInfoByDate(Long userId, String signDate) {
        return baseMapper.selectSignInfoByDate(userId, signDate);
    }

    @Override
    public IPage<AppSignIn> searchListByPage(Integer current, Integer size, AppSignInDto appSignInDto)
            throws JsonProcessingException {
        IPage<AppSignIn> appSignInIPage = new Page<>(current, size);
        QueryWrapper<AppSignIn> wrapper = new QueryWrapper<>();
        if (ObjectUtil.isNotEmpty(appSignInDto)) {
            if (StrUtil.isEmpty(appSignInDto.getRoleCode())) {
                throw new ForestBaseException("角色编码不能为空");
            }
            Long userId = JwtTokenUtils.getId();
            DataReturn<ForesterVO> foresterVODataReturn = fireCommandFeignClient.qryUserDetail(userId);
            if (!ResultCode.SUCCESS.getCode().equals(foresterVODataReturn.getCode())) {
                throw new ForestBaseException(foresterVODataReturn.getErrorMsg());
            }
            ForesterVO foresterVO = foresterVODataReturn.getData();
            String districtCode = foresterVO.getDistrictCode();
            //创建用户ID集合
            final List<Long> fullUserId = new ArrayList<>();
            DataReturn<List<Long>> pageDataDataReturn = fireCommandFeignClient.qryUserIdList(null, null,
                    districtCode, true, appSignInDto.getRoleCode());
            if (!ResultCode.SUCCESS.getCode().equals(pageDataDataReturn.getCode())) {
                throw new ForestBaseException(pageDataDataReturn.getErrorMsg());
            }

            fullUserId.addAll(pageDataDataReturn.getData());
            //把名称模糊查询对应的用户ID查出，并放入到集合
            if (StringUtils.isNotEmpty(appSignInDto.getUserName())) {
                com.telit.common.core.utils.Result<Map<Long, MicroSysUserVo>> mapResult = remoteUpmsService.selectFuzzyRealName(
                        appSignInDto.getUserName(),
                        false);
                Map<Long, MicroSysUserVo> unwrap = FeignUtils.unwrap(mapResult);
                if (CollectionUtil.isNotEmpty(unwrap)) {
                    List<Long> userIdList = Convert.toList(Long.class, unwrap.keySet());
                    List<Long> lastestUserId = fullUserId.stream().map(resultUserId -> userIdList.stream().filter(
                            subUserId -> ObjectUtil.equal(resultUserId, subUserId)).findAny().orElse(null))
                            .filter(Objects::nonNull).collect(Collectors.toList());
                    fullUserId.clear();
                    fullUserId.addAll(lastestUserId);
                } else {
                    return null;
                }
            }
           /* //把角色对应的用户ID查出，并放入到集合
            Result<List<Long>> userIdByRoleCodeResult=upmsFeignClient.queryUserIdByRoleCode(appSignInDto.getRoleCode());
            if(ObjectUtil.isNotEmpty(userIdByRoleCodeResult) && ObjectUtil.isNotEmpty(userIdByRoleCodeResult.getData())){
                List<Long> userIdByRoleCodeList = Convert.toList(Long.class, userIdByRoleCodeResult.getData());
                if(userIdByRoleCodeList !=null && userIdByRoleCodeList.size()>0) {
                    fullUserId.addAll(userIdByRoleCodeList);
                }
            }
            //把名称模糊查询对应的用户ID查出，并放入到集合
            if(StringUtils.isNotEmpty(appSignInDto.getUserName())){
                Result<List<Long>> userIdListResult = upmsFeignClient.queryUserIdByFuzzyName(appSignInDto.getUserName());
                if(ObjectUtil.isNotEmpty(userIdListResult) && ObjectUtil.isNotEmpty(userIdListResult.getData())){
                    List<Long> userIdList = Convert.toList(Long.class, userIdListResult.getData());
                    if(userIdList !=null && userIdList.size()>0) {
                        fullUserId.addAll(userIdList);
                    }
                }
            }*/
            //把最终用户ID集合放入到查询条件
            if (ObjectUtil.isNotEmpty(fullUserId)) {
                wrapper.in("user_id", fullUserId);
            }
            if (ObjectUtil.isNotEmpty(appSignInDto.getStartTime())) {
                wrapper.ge("to_char(sign_in_time,'yyyy-mm-dd hh24:mi')", appSignInDto.getStartTime());
            }
            if (ObjectUtil.isNotEmpty(appSignInDto.getEndTime())) {
                wrapper.le("to_char(sign_in_time,'yyyy-mm-dd hh24:mi')", appSignInDto.getEndTime());
            }
            if (StringUtils.isNotEmpty(appSignInDto.getDistrictCode())) {
                wrapper.eq("district_code", appSignInDto.getDistrictCode());
            }
            if (StringUtils.isNotEmpty(appSignInDto.getDistrictName())) {
                wrapper.eq("district_name", appSignInDto.getDistrictName());
            }
        }
        wrapper.orderByDesc("sign_in_time");
        IPage<AppSignIn> page = baseMapper.selectPage(appSignInIPage, wrapper);
        if (ObjectUtil.isNotEmpty(page.getRecords())) {
            List<AppSignIn> appSignInList = Convert.toList(AppSignIn.class, page.getRecords());
            List<Long> userIdList = appSignInList.stream().map(AppSignIn::getUserId).filter(
                    userId -> ObjectUtil.isNotEmpty(userId)).collect(Collectors.toList());
            final Map<Long, String> nameMap = Maps.newHashMap();
            if (CollectionUtil.isNotEmpty(userIdList)) {
                Result<Map<Long, MicroSysUserVo>> mapResult = remoteUpmsService.selectByBatchIds(userIdList, Boolean.TRUE);
                nameMap.putAll(mapResult.getData().values().stream().collect(
                        Collectors.toMap(MicroSysUserVo::getId, MicroSysUserVo::getRealName)));
            }
            appSignInList.stream().forEach(appSignInResultDTO -> {
                String realName = nameMap.get(appSignInResultDTO.getUserId());
                if (StrUtil.isNotEmpty(realName)) {
                    appSignInResultDTO.setRealName(realName);
                }
            });
        }
        return page;
    }

    @Override
    public AppSignIn selectById(Long id) {
        return baseMapper.selectById(id);
    }

}
